// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Components/GameStateComponent.h"
#include "LoadingProcessInterface.h"

#include "LyraExperienceManagerComponent.generated.h"

#define UE_API LYRAGAME_API

namespace UE::GameFeatures { struct FResult; } // 前向声明

class ULyraExperienceDefinition; // 前向声明

// 经验加载完成时的委托，参数为加载的经验定义
DECLARE_MULTICAST_DELEGATE_OneParam(FOnLyraExperienceLoaded, const ULyraExperienceDefinition* /*Experience*/);

/**
 * 经验加载状态枚举
 */
enum class ELyraExperienceLoadState
{
	Unloaded, // 未加载
	Loading, // 加载中
	LoadingGameFeatures, // 加载游戏功能中
	LoadingChaosTestingDelay, // 混沌测试延迟中
	ExecutingActions, // 执行动作中
	Loaded, // 已加载
	Deactivating // 停用中
};

/**
 * 经验管理器组件，负责管理游戏经验的加载和激活
 */
UCLASS(MinimalAPI)
class ULyraExperienceManagerComponent final : public UGameStateComponent, public ILoadingProcessInterface
{
	GENERATED_BODY()

public:

	UE_API ULyraExperienceManagerComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); // 构造函数

	//~UActorComponent接口
	UE_API virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; // Actor结束游戏时的处理
	//~End of UActorComponent接口

	//~ILoadingProcessInterface接口
	UE_API virtual bool ShouldShowLoadingScreen(FString& OutReason) const override; // 是否应显示加载屏幕
	//~End of ILoadingProcessInterface

	// 尝试设置当前经验，可以是UI或游戏玩法经验
	UE_API void SetCurrentExperience(FPrimaryAssetId ExperienceId);

	// 确保委托在经验加载完成后被调用，在其他委托之前调用。如果经验已加载，立即调用委托。
	UE_API void CallOrRegister_OnExperienceLoaded_HighPriority(FOnLyraExperienceLoaded::FDelegate&& Delegate);

	// 确保委托在经验加载完成后被调用。如果经验已加载，立即调用委托。
	UE_API void CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate&& Delegate);

	// 确保委托在经验加载完成后被调用。如果经验已加载，立即调用委托。
	UE_API void CallOrRegister_OnExperienceLoaded_LowPriority(FOnLyraExperienceLoaded::FDelegate&& Delegate);

	// 返回当前完全加载的经验，如果尚未加载则断言
	UE_API const ULyraExperienceDefinition* GetCurrentExperienceChecked() const;

	// 返回经验是否已完全加载
	UE_API bool IsExperienceLoaded() const;

private:
	UFUNCTION()
	void OnRep_CurrentExperience(); // 当前经验复制时的回调

	void StartExperienceLoad(); // 开始经验加载
	void OnExperienceLoadComplete(); // 经验加载完成回调
	void OnGameFeaturePluginLoadComplete(const UE::GameFeatures::FResult& Result); // 游戏功能插件加载完成回调
	void OnExperienceFullLoadCompleted(); // 经验完全加载完成回调

	void OnActionDeactivationCompleted(); // 动作停用完成回调
	void OnAllActionsDeactivated(); // 所有动作停用完成回调

private:
	UPROPERTY(ReplicatedUsing=OnRep_CurrentExperience)
	TObjectPtr<const ULyraExperienceDefinition> CurrentExperience; // 当前经验定义

	ELyraExperienceLoadState LoadState = ELyraExperienceLoadState::Unloaded; // 当前加载状态

	int32 NumGameFeaturePluginsLoading = 0; // 正在加载的游戏功能插件数量
	TArray<FString> GameFeaturePluginURLs; // 游戏功能插件URL列表

	int32 NumObservedPausers = 0; // 观察到的暂停者数量
	int32 NumExpectedPausers = 0; // 预期的暂停者数量

	/**
	 * 经验加载完成后立即调用的委托（例如，为常规游戏玩法设置的子系统）
	 */
	FOnLyraExperienceLoaded OnExperienceLoaded_HighPriority; // 高优先级经验加载委托

	/** 经验加载完成后调用的委托 */
	FOnLyraExperienceLoaded OnExperienceLoaded; // 普通优先级经验加载委托

	/** 经验加载完成后调用的委托 */
	FOnLyraExperienceLoaded OnExperienceLoaded_LowPriority; // 低优先级经验加载委托
};

#undef UE_API